<template>
  <div class="main-select" ref="main" @click="() => (showOption = true)">
    <div
      class="select-top"
      :style="selectTopStyle"
    >
      <div class="left thumb">
        <div class="shows" v-show="selectValue !== undefined">
          <div class="overOne" :style="{ fontSize: size, color: valueColor }">
            {{ selectOption ? selectOption[label] : selectValue }}
          </div>
        </div>

        <div
          class="input"
          v-show="selectValue === undefined"
          :style="{ fontSize: size }"
        >
          <span
            v-show="!searchable"
            :style="{ fontSize: size, color: searchColor, fontWeight: 400 }"
            >{{ placeholder }}</span
          >
          <input
            :style="{ fontSize: size, color: searchColor }"
            @input="() => (is_loading = true)"
            :placeholder="placeholder"
            v-model="searchText"
            v-show="searchable"
          />
        </div>
      </div>

      <div class="right-icon thumb">
        <!-- <img
        :class="[showOption ? `rotation` : ``]"
        :src="publicUrl(`/images/arrow-gray.png`)"
      /> -->
        <div
          :class="['icon', 'close']"
          @click.stop="clear"
          v-show="clearable && selectValue !== undefined"
          title="清空"
        >
          <SvgIcon
            :name="`close`"
            class="svg"
            :color="styleColor"
            :style="{ fontSize: size }"
          ></SvgIcon>
        </div>

        <div
          :class="['icon', 'transition', showOption ? `rotation` : ``]"
          v-show="!is_loading"
        >
          <SvgIcon
            :name="`arrowSel`"
            class="svg"
            :color="styleColor"
            :style="{ fontSize: size }"
          ></SvgIcon>
        </div>
        <div :class="['loading', 'icon']" v-show="is_loading">
          <SvgIcon
            :name="`loading`"
            class="svg"
            :color="styleColor"
            :style="{ fontSize: size }"
          ></SvgIcon>
        </div>
      </div>
    </div>
    <div
      class="option-list"
      v-show="showOption && !is_loading"
      :style="{...optionStyle}"
    >
      <div class="none" v-show="optionList.length < 1" :style="{color:noneColor}">暂无数据</div>

      <div
        :class="[
          'part',
          'thumb',
          reduce(item) === selectValue ? 'sel' : 'nosel',
        ]"
        :style="{
          '--select-style-color': optionColor,
          '--value-style-color': valueColor,
        }"
        v-for="item in optionList"
        @click.stop="() => setValue(item)"
      >
        {{ item[label] }}
      </div>
    </div>
  </div>
</template>
<script setup lang="ts" name="">
import { ref, onMounted, computed, watch ,CSSProperties } from "vue";
import { onClickOutside } from "@vueuse/core";
import SvgIcon from "@/components/SvgIcon/index.vue";
import { refDebounced } from "@vueuse/core";

interface Props {
  options?: Array<{ [key: string]: any }>; //可选数据
  label?: string;                          //选项显示的字段
  placeholder?: string;                    //空选项时显示的文本框
  selectTopCss?:CSSProperties;             //选项头部的css自定义
  optionCss?:CSSProperties;                //选项list的css自定义
  reduce?: (option: any) => any;           //最后选择成功的value值
  size?: string;                           //文字和图标大小
  clearable?: boolean;                     //是否显示清空选项
  searchable?: boolean;                    //是否显示搜索选项
  border?: boolean;                        //是否显示边框
  borderColor?: string;                    //边框颜色
  valueColor?: string;                     //选择完成后的文本颜色  
  noneColor?:string;                       //空数据时文本颜色
  searchColor?: string;                    //搜索文本颜色
  loading?: boolean;                       //是否加载中图标
  styleColor?: string;                     //图标颜色
  optionColor?: string;                    //选中和指向时的颜色
  value?: undefined | string | number;     //双向绑定默认值
}
const main = ref<any>(null);

const props = withDefaults(defineProps<Props>(), {
  options: () => [],      
  placeholder: `请选择`,   
  label: `label`,        
  clearable: false,       //是否可以清空选项
  searchable: false,      //是否显示搜索框
  styleColor: "#dedede",  //图标颜色
  size: "0.08rem",        //文字大小
  selectTopCss:()=>{
    return {}
  },
  optionCss:()=>{
    return {}
  },
  optionColor: "#3644bf",
  border: true,
  noneColor:"#989797",
  borderColor: `#dedede`,
  valueColor: `#2D2D2D`,
  searchColor: `#807d7d`,
  loading: false,
  reduce: (option: any) => option.value,
  value: undefined,
});

watch(
  () => props.loading,
  (newValue) => {
    is_loading.value = newValue;
  }
);

const optionList = ref<Array<{ [key: string]: any }>>(props.options);

const searchText = ref<string>("");

const debounced = refDebounced(searchText, 1000);

const selectTopStyle =  computed(():CSSProperties=>{
  return  {border: props.border ? `1px solid ${props.borderColor}` : undefined,...props.selectTopCss};
})
const optionStyle =  computed(():CSSProperties=>{
  return { 
        'border-bottom': props.border ? `1px solid ${props.borderColor}` : undefined,
        'border-left': props.border ? `1px solid ${props.borderColor}` : undefined,
        'border-right': props.border ? `1px solid ${props.borderColor}` : undefined,
        'max-height': `calc(8 * 0.2rem)` ,
         ...props.optionCss
      };
})

watch(
  () => debounced.value,
  (newValue) => {
    is_loading.value = true;

    if (newValue === "") {
      optionList.value = props.options;
    } else {
      optionList.value = props.options.filter(
        (item: { [key: string]: any }) => {
          return typeof item[props.label] === "string"
            ? item[props.label].indexOf(newValue) !== -1
            : false;
        }
      );
    }
    is_loading.value = false;
  }
);

const is_loading = ref<boolean>(props.loading);

const showOption = ref<boolean>(true);

const selectValue = ref<number | string | undefined>(props.value);

const emtis = defineEmits<{
  (event: "update:value", value: undefined | string | number): void;
  (event: "change", value: undefined | string | number): void;
}>();

watch(
  () => props.value,
  (newValue) => {
    selectValue.value = newValue;
  }
);

const selectOption = computed(() => {
  return props.options.find((item: { [key: string]: any }) => {
    return props.reduce(item) === selectValue.value;
  });
});

onClickOutside(main, () => {
  showOption.value = false;
});

onMounted(() => {
  showOption.value = false;
});

const setValue = (item: { [key: string]: any }) => {
  showOption.value = false;
  let newValue = props.reduce(item);
  if (newValue !== selectValue.value) {
    selectValue.value = newValue;
    searchText.value = "";
    emtis("update:value", selectValue.value);
    emtis("change", selectValue.value);
  }
};

const clear = () => {
  selectValue.value = undefined;
  emtis("update:value", selectValue.value);
  emtis("change", selectValue.value);
};
</script>
<style scoped lang="scss">
@import "./index.scss";
</style>
